#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/12/12 18:35
# @Author  : FuKai ZHANG
# @File    : mysql_control.py
# @Description :MySQL封装，支持增删改查等操作
import datetime
import decimal
from warnings import filterwarnings
import pymysql
from typing import Text
from config .global_config import config
from utils.logging_tools.log_control import ERROR

# 忽略 Mysql 告警信息
filterwarnings("ignore", category=pymysql.Warning)


class MysqlDB:
    """ mysql 封装 ,多进程执行，每个进程都会有自己的连接实例，
    可以考虑使用conftest和fixture结合的方式，作用于session，由主进程同步给子进程"""

    def __init__(self):

        try:
            # 建立数据库连接
            self.conn = pymysql.connect(
                host=config.mysql_db.host,
                user=config.mysql_db.user,
                password=config.mysql_db.password,
                port=config.mysql_db.port
            )

            # 使用 cursor 方法获取操作游标，得到一个可以执行sql语句，并且操作结果为字典返回的游标
            self.cur = self.conn.cursor(cursor=pymysql.cursors.DictCursor)
        except AttributeError as error:
            ERROR.logger.error("数据库连接失败，失败原因 %s", error)

    def __del__(self):
        """对象销毁时自动调用"""
        try:
            # 关闭游标
            self.cur.close()
            # 关闭连接
            self.conn.close()
        except AttributeError as error:
            ERROR.logger.error("数据库连接关闭失败，失败原因 %s", error)

    def query(self, sql, state="all"):
        """
            查询
            :param sql:
            :param state:  all 是默认查询全部
            :return:
            """
        try:
            self.cur.execute(sql)

            if state == "all":
                # 查询全部
                data = self.cur.fetchall()
            else:
                # 查询单条
                data = self.cur.fetchone()
            return data
        except AttributeError as error_data:
            ERROR.logger.error("数据库连接失败，失败原因 %s", error_data)
            raise

    def execute(self, sql: Text):
        """
            更新 、 删除、 新增
            :param sql:
            :return:
            """
        try:
            # 使用 execute 操作 sql
            rows = self.cur.execute(sql)
            # 提交事务
            self.conn.commit()
            return rows
        except AttributeError as error:
            ERROR.logger.error("数据库连接失败，失败原因 %s", error)
            # 如果事务异常，则回滚数据
            self.conn.rollback()
            raise

    @classmethod
    def sql_data_handler(cls, query_data, data):
        """
        处理部分类型sql查询出来的数据格式
        @param query_data: 查询出来的sql数据
        @param data: 数据池
        @return:
        """
        # 将sql 返回的所有内容全部放入对象中
        for key, value in query_data.items():  # isinstance(object, classinfo) 判断是否为某类型
            if isinstance(value, decimal.Decimal):  # 精准数据类型，精确小数
                data[key] = float(value)
            elif isinstance(value, datetime.datetime):  # 时间类型
                data[key] = str(value)
            else:
                data[key] = value
        return data
